package com.hoperun.checkcloth.ui

import android.os.Bundle
import android.view.KeyEvent
import android.view.inputmethod.EditorInfo
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.addTextChangedListener
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.hoperun.checkcloth.R
import com.hoperun.checkcloth.adapter.BoltFlawNumberAdapter
import com.hoperun.checkcloth.adapter.BoltFlawRemarkAdapter
import com.hoperun.checkcloth.adapter.BoltFlawTypeAdapter
import com.hoperun.checkcloth.databinding.LeftoverBoltClothCheckingActivityBinding
import com.hoperun.checkcloth.fragment.CountDialogFragment
import com.hoperun.checkcloth.net.ClothFlawInfo
import com.hoperun.checkcloth.ui.dialog.SimpleDialog
import com.hoperun.checkcloth.util.hideSoftInput
import com.hoperun.checkcloth.view.WaitDialog
import com.hoperun.checkcloth.viewmodel.LeftOverBoltClothViewModel
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import java.util.concurrent.TimeUnit

class LeftOverBoltClothActivity : AppCompatActivity() {
    private lateinit var binding: LeftoverBoltClothCheckingActivityBinding
    private lateinit var flawTypeAdapter: BoltFlawTypeAdapter
    private lateinit var remarkAdapter: BoltFlawRemarkAdapter
    private lateinit var flawNumberAdapter: BoltFlawNumberAdapter
    private lateinit var viewModel: LeftOverBoltClothViewModel
    private lateinit var loadingDialog: WaitDialog
    private val disposable = CompositeDisposable()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(this)[LeftOverBoltClothViewModel::class.java]
        binding = DataBindingUtil.setContentView(this, R.layout.leftover_bolt_cloth_checking_activity)
        binding.workerName = ""
        initViews()
        setupBinding()
        setupViewModel()
    }

    private fun initViews() {
        loadingDialog = WaitDialog(this)
        binding.rlFlawType.layoutManager = GridLayoutManager(this, 4)
        binding.rlFlawRemark.layoutManager = GridLayoutManager(this, 4)
        binding.rlFlaw.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

        flawTypeAdapter = BoltFlawTypeAdapter { item -> viewModel.onFlawTypeItemClick(item) }
        remarkAdapter = BoltFlawRemarkAdapter { item -> viewModel.onRemarkItemClick(item) }
        flawNumberAdapter = BoltFlawNumberAdapter()
        flawNumberAdapter.onIemSetCountClick = { item -> viewModel.onFlawInfoSetCountClick(item) }
        flawNumberAdapter.onItemDeleteClick = { item -> viewModel.onFlawInfoItemDelete(item) }

        binding.rlFlawType.adapter = flawTypeAdapter
        binding.rlFlawRemark.adapter = remarkAdapter
        binding.rlFlaw.adapter = flawNumberAdapter

        binding.etMonadNo.post {
            binding.etMonadNo.requestFocus()
        }


        val clothTextChangedDisposable = Flowable.create<String>({ emitter ->
            binding.etMonadNo.addTextChangedListener(afterTextChanged = {
                emitter.onNext("")
            })
        }, BackpressureStrategy.BUFFER)
                .debounce(200, TimeUnit.MILLISECONDS)
                .subscribe { viewModel.onClothNoEditTextChanged() }


        // OnEditorActionListener 事件中，扫描枪扫描行为会让该回调方法调两次，而手动输入回车只调一次
        // 所以用 RxJava 的 debounce 设置 500ms 的时间间隔
        val inputSoftDisposable = Flowable.create<String>({ emitter ->
            binding.etMonadNo.setOnEditorActionListener { v, actionId, event ->
                // case1 对应扫描枪事件
                val debugStr = StringBuilder()
                debugStr.append("event $event")
                val case1 = event?.let { it.keyCode == KeyEvent.KEYCODE_ENTER && it.action == KeyEvent.ACTION_UP }
                        ?: false

                // case2 对应扫码枪事件
                val case2 = event?.let { it.keyCode == KeyEvent.KEYCODE_ENTER && it.action == KeyEvent.ACTION_DOWN }
                        ?: false

                // case3 对应手动输入，然后点击软键盘的完成键
                val case3 = actionId == EditorInfo.IME_ACTION_DONE
                debugStr.append(" $actionId")
                if (case1 || case2 || case3) {
                    emitter.onNext(binding.etMonadNo.text.toString())
                    hideSoftInput(v)
                    return@setOnEditorActionListener true
                }

                return@setOnEditorActionListener false
            }
        }, BackpressureStrategy.BUFFER)
                .debounce(200, TimeUnit.MILLISECONDS)
                .subscribe { text ->
                    viewModel.requestInformation(text)
                }

        disposable.add(inputSoftDisposable)
        disposable.add(clothTextChangedDisposable)
    }

    private fun setupBinding() {
        binding.viewModel = viewModel
        binding.setOnBackClick { onBackPressed() }
    }

    private fun setupViewModel() {

        viewModel.loading.observe(this, { show ->
            if (show) {
                loadingDialog.show()
            } else {
                loadingDialog.dismiss()
            }
        })

        viewModel.message.observe(this, { message ->
            Toast.makeText(baseContext, message, Toast.LENGTH_SHORT).show()
        })

        viewModel.messageRes.observe(this, { res ->
            Toast.makeText(baseContext, res, Toast.LENGTH_SHORT).show()
        })

        viewModel.dialogMessage.observe(this, { message ->
            SimpleDialog.newInstance(message).show(supportFragmentManager, "DialogTip")
        })

        viewModel.dialogMessageRes.observe(this, { msgRes ->
            SimpleDialog.newInstance(getString(msgRes)).show(supportFragmentManager, "DialogTip")
        })

        viewModel.flawTypes.observe(this, { list ->
            flawTypeAdapter.setDataSet(list)
        })

        viewModel.remarks.observe(this, { list ->
            remarkAdapter.setDataSet(list)
        })

        viewModel.flawInfoList.observe(this, { list ->
            flawNumberAdapter.setDataSet(list)
        })

        viewModel.setCount.observe(this, {
            showSetCountDialog(it)
        })

        viewModel.commit.observe(this, { success ->
            if (success) {
                binding.etMonadNo.text = null
                SimpleDialog.newInstance(getString(R.string.insert_success)).show(supportFragmentManager, "Insert Success")
            }

        })

        // 开始时加载数据
        viewModel.loadData()
    }

    override fun onDestroy() {
        super.onDestroy()
        disposable.dispose()
    }

    private fun showSetCountDialog(item: ClothFlawInfo) {
        CountDialogFragment.newInstance(item.number).apply {
            setOnOKClickListener { count ->
                viewModel.onSetFlawInfoCount(item, count)
                dismissAllowingStateLoss()
            }
            show(supportFragmentManager, "SetCount")
        }
    }

}